백준 9252번 - LCS 2
백준 9251번 - LCS 의 역추적이 추가된 버전이다.
LCS의 길이를 구하는 것 + LCS를 구하는 문제
LCS를 직접 구해야하기 때문에 백준 9251번 - LCS 처럼 1차원 배열로 풀 수 없다.
2차원 배열로 흔적을 남겨놔야한다.
코드
틀린코드
const readline=require("readline")
const rl=readline.createInterface({
input:process.stdin,
output:process.stdout
})
let input=[]
rl.on("line",(line)=>{
input.push(line)
})
rl.on("close",()=>{
const a=input[0]
const b=input[1]
const dp=new Array(b.length).fill(null).map(()=>new Array(a.length).fill(0))
for(let i=0;i<b.length;i++){
for(let j=0;j<a.length;j++){
if(a[j]==b[i]){
dp[i][j]=i==0||j==0? 1 : dp[i-1][j-1]+1
}
else{
dp[i][j]=Math.max(i==0? 0 : dp[i-1][j],j==0? 0: dp[i][j-1])
}
}
}
let result=[]
let x=b.length-1
let y=a.length-1
while(true){
const cur=dp[x][y]
if(x>0 && dp[x-1][y]==cur){
x--;
}
else if(y>0 && dp[x][y-1]==cur){
y--;
}
else{
result.push(b[x])
x--;
y--;
}
if(x<0 || y<0){
break
}
}
console.log(result.length)
console.log(result.reverse().join(""))
})
처음에 이렇게 풀었는데 틀렸다.
이유는 즉슨, 역추적하는 과정에서 조건이 잘못됐다.
- 범위를 벗어나지 않는다.(x<0 || y<0)
- 역추적이 끝난다.(dp[x][y] == 0)
2번의 조건을 추가해주지 않아서 틀렸다.
정답 코드
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
rl.on("line", (line) => {
input.push(line);
});
rl.on("close", () => {
const a = input[0], b = input[1];
const dp = Array.from({ length: b.length }, () => Array(a.length).fill(0));
for (let i = 0; i < b.length; i++) {
for (let j = 0; j < a.length; j++) {
if (b[i] === a[j]) {
dp[i][j] = (i > 0 && j > 0) ? dp[i - 1][j - 1] + 1 : 1;
} else {
dp[i][j] = Math.max(i > 0 ? dp[i - 1][j] : 0, j > 0 ? dp[i][j - 1] : 0);
}
}
}
let x = b.length - 1, y = a.length - 1;
let result = [];
while (x >= 0 && y >= 0 && dp[x][y] > 0) {
if (x > 0 && dp[x - 1][y] === dp[x][y]) {
x--;
} else if (y > 0 && dp[x][y - 1] === dp[x][y]) {
y--;
} else {
result.push(b[x]);
x--;
y--;
}
}
console.log(result.length);
console.log(result.reverse().join(""));
});
정제 코드
dp 배열에 테두리 공백을 만들고 조건을 dp 값이 아닌 해당 비교값이 같은지로 하면 더 정제될 수 있다.
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
rl.on("line", (line) => {
input.push(line.trim());
});
rl.on("close", () => {
const strA = input[0];
const strB = input[1];
const lenA = strA.length;
const lenB = strB.length;
// DP 테이블 초기화
const dp = Array.from({ length: lenB + 1 }, () => new Array(lenA + 1).fill(0));
// LCS 길이 계산
for (let i = 1; i <= lenB; i++) {
for (let j = 1; j <= lenA; j++) {
dp[i][j] = strB[i-1] === strA[j-1]
? dp[i-1][j-1] + 1
: Math.max(dp[i-1][j], dp[i][j-1]);
}
}
// LCS 역추적
let lcs = [];
let i = lenB, j = lenA;
while (i > 0 && j > 0) {
if (strB[i-1] === strA[j-1]) {
lcs.push(strB[i-1]);
i--;
j--;
} else if (dp[i-1][j] > dp[i][j-1]) {
i--;
} else {
j--;
}
}
console.log(lcs.length);
lcs.length > 0 && console.log(lcs.reverse().join(''));
});